/** 
 * File: Course.java
 * Project: CMSC 345 Course Registration System, Fall 2010
 * Author: David Chong
 * Date: 12/5/10
 * E-mail: ro62899@umbc.edu
 * This class is used to represent a Course.  It contains fields to hold 
 * different stuff expected to be associated with a Course such as a
 * instructor's name and the student list.  It contains methods to retrieve
 * and modify fields.   In addition, there is methods to display the Course
 * information.  The class implements the Comparable interface.
 * 
 * 
 * Class Invariant: The integer fields can not be negative and the object
 *                  references can not be null
 */

package registeringSystem;

import com.google.appengine.api.datastore.Key;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import java.util.ArrayList;

@PersistenceCapable
public class Course implements Comparable<Course> 
{
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Key theKey;
	
	@Persistent
	private String courseID;
	
	@Persistent
	private ArrayList<User> studentList;
	
	@Persistent
	private String semester;
	
	@Persistent
	private int year;
	
	@Persistent
	private int capacity;               
	
	@Persistent
	private String courseName;
	
	@Persistent
	private int sectionNumber;
	
	@Persistent
	private String instructorName;
	
	@Persistent
	private String teachingAssistantName;
	
	@Persistent
	private Location teachingLocation;
	
	@Persistent
	private String daysHeld;
	
	@Persistent
	private Time timeHeld;
	
	@Persistent
	private int numberOfWeeks;
	
	@Persistent
	private int numberOfTotalCredits;
	
	@Persistent
	private String courseExcerpt;
	
	@Persistent
	private MonthDayYear startDate;
	
	@Persistent
	private MonthDayYear endDate;
	
	@Persistent
	private ArrayList<String> prerequisitesNeededForThisCourse;
	
	@Persistent
	private ArrayList<User> waitList;
	
	@Persistent
	private ArrayList<User> withdrawList;
	
	@Persistent
	private static int NUMBER_OF_SPOTS_FOR_THE_WAITLIST;
	
	
	
	/** 
     * Name: Course <br><br>
     * The default constructor that initializes its private data members.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Initialize the data fields with the arguments.
     */
	public Course()
	{
		courseID = "";
		studentList = new ArrayList<User>();
		semester = "";
		year = 0;
		capacity = 0;
		courseName = "";
		sectionNumber = 0;
		instructorName = "";
		teachingAssistantName = "";
		teachingLocation = new Location();
		daysHeld = "";
		timeHeld = new Time();
		numberOfWeeks = 0;
		numberOfTotalCredits = 0;
		courseExcerpt = "";
		startDate = new MonthDayYear();
		endDate = new MonthDayYear();
		prerequisitesNeededForThisCourse = new ArrayList<String>();
		waitList = new ArrayList<User>();
		withdrawList = new ArrayList<User>();
	} // end of default constructor
	
	
	
	/** 
     * Name: Course <br><br>
     * The constructor that initializes the private data members with the 
     * values passed in.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Initialize the data fields with the arguments.
     * @param semester - the semester for the Course
     * @param year - the year that it will be held
     * @param capacity - the capacity of the Course
     * @param courseName - the name for the Course
     * @param sectionNumber - the section number for the Course
     * @param instructorName - the instructor's name for the Course
     * @param location - the location where the Course will be held
     * @param daysHeld - the days when the class will be held
     * @param timeHeld - the time when the class is held
     * @param numberOfWeeks - the number of weeks for the course
     * @param numberOfCredits - the number of credits for the Course
     * @param courseExcerpt - a summary about the Course
     * @param startDate - the start date for the Course
     * @param endDate - the end date for the Course
     * @param prereqs - the prerequisites needed for the Course
     * @param waitList - the wait list for the Course
     * @param withdrawList - the withdraw list for the Course
     * @throws NullReferenceException is thrown is when a null reference is
     *         passed in
     * @throws NotValidArgumentException is thrown if a negative number is
     *         passed in
     */
	public Course(String semester, int year, int capacity, String courseName,
			      int sectionNumber, String instructorName, Location location, 
			      String daysHeld, Time timeHeld, int numberOfWeeks, 
			      int numberOfCredits, String courseExcerpt, 
			      MonthDayYear startDate, MonthDayYear endDate, 
			      ArrayList<String> prereqs)
	                                          throws NotValidArgumentException,
	                                                     NullReferenceException
	{
		boolean isThereAnyNullReferences = semester == null ||
                                           courseName == null ||
                                           instructorName == null ||
                                           daysHeld == null ||
                                           timeHeld == null ||
                                           courseExcerpt == null ||
                                           prereqs == null;
        
        boolean isThereAnyNegativeNumber = year < 0 ||
                                           capacity < 0;


        if(isThereAnyNullReferences)
            throw new NullReferenceException("Can not create the Course " +
                                             "object because a null " +
                                             "reference was passed in!\n");

        else if(isThereAnyNegativeNumber)
            throw new NotValidArgumentException("Can not create the Course " +
                                                "object because a negative " +
                                                "number was passed in!\n");

        // other wise, it is okay to use the values passed in
		this.courseID = "";
		this.studentList = new ArrayList<User>();
		this.semester = semester;
		this.year = year;
		this.capacity = capacity;
		this.courseName = courseName;
		this.sectionNumber = sectionNumber;
		this.instructorName = instructorName;
		this.teachingLocation = location;
		this.daysHeld = daysHeld;
		this.timeHeld = timeHeld;
		this.numberOfWeeks = numberOfWeeks;
		this.numberOfTotalCredits = numberOfCredits;
		this.courseExcerpt = courseExcerpt;
		this.startDate = startDate;
		this.endDate = endDate;
		this.prerequisitesNeededForThisCourse = prereqs;
		this.waitList = new ArrayList<User>();
		this.withdrawList= new ArrayList<User>();	
	} // end of constructor
	
	
	
	/** 
     * Name: Course <br><br>
     * The constructor that initializes the private data members with the 
     * values passed in.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Initialize the data fields with the arguments.
     * @param courseID - the course ID
     * @param studentList - the list containing the students
     * @param semester - the semester for the Course
     * @param year - the year that it will be held
     * @param capacity - the capacity of the Course
     * @param courseName - the name for the Course
     * @param sectionNumber - the section number for the Course
     * @param instructorName - the instructor's name for the Course
     * @param teachingAssistantName - the name of the teaching assistant
     * @param teachingLocation - the location where the Course will be held
     * @param daysHeld - the days when the class will be held
     * @param timeHeld - the time when the class is held
     * @param numberOfWeeks - the number of weeks for the course
     * @param numberOfCredits - the number of credits for the Course
     * @param courseExcerpt - a summary about the Course
     * @param startDate - the start date for the Course
     * @param endDate - the end date for the Course
     * @param prerequistisitesNeed - the prerequisites needed for the Course
     * @param waitList - the wait list for the Course
     * @param withdrawList - the withdraw list for the Course
     * @throws NullReferenceException is thrown is when a null reference is
     *         passed in
     * @throws NotValidArgumentException is thrown if a negative number is
     *         passed in
     */
	public Course(String courseID, ArrayList<User> studentList, 
			      String semester, int year, int capacity,
			      String courseName, int sectionNumber, String instructorName,
			      String teachingAssistantName, Location teachingLocation,
			      String daysHeld, Time timeHeld, int numberOfWeeks,
			      int numberOfCredits, String courseExcerpt, 
			      MonthDayYear startDate, MonthDayYear endDate, 
			      ArrayList<String> prerequisitesNeeded,
			      ArrayList<User> waitList, ArrayList<User> withdrawList)
	                                          throws NotValidArgumentException,
	                                                     NullReferenceException
	                                 
	{
		boolean isThereAnyNullReferences = courseID == null ||
		                                   studentList == null ||
		                                   semester == null ||
		                                   courseName == null ||
		                                   instructorName == null ||
		                                   teachingAssistantName == null ||
		                                   teachingLocation == null ||
		                                   daysHeld == null ||
		                                   timeHeld == null ||
		                                   courseExcerpt == null ||
		                                   startDate == null ||
		                                   endDate == null ||
		                                   prerequisitesNeeded == null ||
		                                   waitList == null ||
		                                   withdrawList == null;
		                                   
		boolean isThereAnyNegativeNumber = year < 0 ||
		                                   capacity < 0 ||
		                                   sectionNumber < 0 ||
		                                   numberOfWeeks < 0 ||
		                                   numberOfTotalCredits < 0;
		
		
		if(isThereAnyNullReferences)
			throw new NullReferenceException("Can not create the Course " +
					                         "object because a null " +
					                         "reference was passed in!\n");
		
		else if(isThereAnyNegativeNumber)
			throw new NotValidArgumentException("Can not create the Course " +
					                            "object because a negative " +
					                            "number was passed in!\n");
		
		// other wise, it is okay to use the values passed in                                   
		this.courseID = courseID;
		this.studentList = studentList;
		this.semester = semester;
		this.year = year;
		this.capacity = capacity;
		this.courseName = courseName;
		this.sectionNumber = sectionNumber;
		this.instructorName = instructorName;
		this.teachingAssistantName = teachingAssistantName;
		this.teachingLocation = teachingLocation;
		this.daysHeld = daysHeld;
		this.timeHeld = timeHeld;
		this.numberOfWeeks = numberOfWeeks;
		this.numberOfTotalCredits = numberOfCredits;
		this.courseExcerpt = courseExcerpt;
		this.startDate = startDate;
		this.endDate = endDate;
		this.prerequisitesNeededForThisCourse = prerequisitesNeeded;
		this.waitList = waitList;
		this.withdrawList = withdrawList;		
	} // end of constructor
	
	
	
	/** 
     * Name: Course <br><br>
     * The copy constructor that initializes the private data members with the
     * same values with as the argument.  It is a deep copy.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Performs a deep copy of the argument object.
     * @param copyThis - the object that will be copied
     * @throws NullReferenceException is thrown is when a null reference is
     *         passed in
     */
    public Course(Course copyThis) throws NullReferenceException
    {
    	if(copyThis == null)
    		throw new NullReferenceException("Can not copy and create the Course " +
    				                         "object because a null reference " +
    				                         "was passed in!\n");
    	
    	courseID = copyThis.courseID;
    	studentList = copyStudentList(copyThis);
    	year = copyThis.year;
    	capacity = copyThis.capacity;
    	courseName = copyThis.courseName;
    	sectionNumber = copyThis.sectionNumber;
    	instructorName = copyThis.instructorName;
    	teachingAssistantName = copyThis.teachingAssistantName;
    	teachingLocation = new Location(copyThis.teachingLocation);
    	daysHeld = copyThis.daysHeld;
    	timeHeld = new Time(timeHeld);
    	numberOfWeeks = copyThis.numberOfWeeks;
    	numberOfTotalCredits = copyThis.numberOfTotalCredits;
    	courseExcerpt = copyThis.courseExcerpt;
    	startDate = new MonthDayYear(copyThis.startDate);
    	endDate = new MonthDayYear(copyThis.endDate);
    	prerequisitesNeededForThisCourse = 
    		                    copyPrerequisitesNeededForThisCourse(copyThis);
    	waitList = copyWaitList(copyThis);
    	withdrawList = copyWithdrawList(copyThis);
    } // end of copy constructor
    
    
    
    /** 
     * Name: copyStudentList <br><br>
     * Makes a deep copy of the student list and returns a reference to it.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a reference to the copied student list. <br>
     * @param copyThis - the Course object that will have its student list
     *                   copied
     */
    private ArrayList<User> copyStudentList(Course copyThis)
    {
    	ArrayList<User> newStudentList = new ArrayList<User>();
    	
    	for(User theUser: copyThis.studentList)
			try 
    	    {
				newStudentList.add(new User(theUser));
			} 
    	    
    	    catch (NullReferenceException nre) 
    	    {
				; // do not add the null references
			}
    	
    	return newStudentList;
    } // end of copyStudentList

    
    
    /** 
     * Name: copyPrerequisitiesNeededForTheCourse <br><br>
     * Makes a deep copy of the prerequisites list and returns a reference to
     * it.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a reference to the copied prerequisites list.
     * <br>
     * @param copyThis - the Course object that will have its prerequisites
     *                   list copied
     */
    private ArrayList<String> copyPrerequisitesNeededForThisCourse(
    		                                                   Course copyThis)
    {
    	ArrayList<String> newPrerequisitesNeededForThisCourse = 
    		                                           new ArrayList<String>();
    	
    	for(String day: copyThis.prerequisitesNeededForThisCourse)
    		newPrerequisitesNeededForThisCourse.add(day);
    	
    	return newPrerequisitesNeededForThisCourse;
    } // end of copyPrerequisitesNeededForThisCourse
    
    
    
    /** 
     * Name: copyWaitList <br><br>
     * Makes a deep copy of the wait list and returns a reference to it.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a reference to the copied wait list. <br>
     * @param copyThis - the Course object that will have its wait list
     *                   copied
     */
    private ArrayList<User> copyWaitList(Course copyThis)
    {
    	ArrayList<User> newWaitList = new ArrayList<User>();
    	
    	for(User theUser: copyThis.waitList)
			try 
    	    {
				newWaitList.add(new User(theUser));
			} 
    	    
    	    catch (NullReferenceException nre) 
    	    {
				; // do not add the null references
			}
    	
    	return newWaitList;
    } // end of copyWaitList
    
    
    
    /** 
     * Name: copyWithdrawList <br><br>
     * Makes a deep copy of the withdraw list and returns a reference to it.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a reference to the copied withdraw list. <br>
     * @param copyThis - the Course object that will have its withdraw list
     *                   copied
     */
    private ArrayList<User> copyWithdrawList(Course copyThis)
    {
    	ArrayList<User> newWithdrawList = new ArrayList<User>();
    	
    	for(User theUser: copyThis.withdrawList)
			try 
    	    {
				newWithdrawList.add(new User(theUser));
			} 
    	    
    	    catch (NullReferenceException nre) 
    	    {
				; // do not add the null references
			}
    	
    	return newWithdrawList;
    } // end of copyWaitList
    
	
	
	/** 
     * Name: getTheKey <br><br>
     * An accessor method that retrieves the key for the object in the
     * Google datastore.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the key. <br>
     * @param None
     */
	public Key getTheKey()
	{
		return theKey;
	} // end of getTheKey()
	
	
	
	/** 
     * Name: getCourseID <br><br>
     * An accessor method that retrieves the courseID.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the courseID time. <br>
     * @param None
     */
	public String getCourseID()
	{
		return courseID;
	} // end of getCourseID()
	
	
	
	/** 
     * Name: getStudentList <br><br>
     * An accessor method that retrieves the student list.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the student list. <br>
     * @param None
     */
	public ArrayList<User> getStudentList()
	{
		return studentList;
	} // end of getStudentList()
	
	
	
	/** 
     * Name: getSemester <br><br>
     * An accessor method that retrieves the semester.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the semester. <br>
     * @param None
     */
	public String getSemester()
	{
		return semester;
	} // end of getSemester()
	
	
	
	/** 
     * Name: getYear <br><br>
     * An accessor method that retrieves the year.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the year the class was held. <br>
     * @param None
     */
	public int getYear()
	{
		return year;
	} // end of getYear()
	
	
	
	/** 
     * Name: getCapacity <br><br>
     * An accessor method that retrieves the capacity of the class.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the capacity of the class. <br>
     * @param None
     */
	public int getCapacity()
	{
		return capacity;
	} // end of getCapacity()
	
	
	
	/** 
     * Name: getCourseName <br><br>
     * An accessor method that retrieves the course name.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the course name. <br>
     * @param None
     */
	public String getCourseName()
	{
		return courseName;
	} // end of getCourseName()
	
	
	
	/** 
     * Name: getSectionNumber <br><br>
     * An accessor method that retrieves the section number.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the section number. <br>
     * @param None
     */
	public int getSectionNumber()
	{
		return sectionNumber;
	} // end of getSectionNumber()
	
	
	
	/** 
     * Name: getInstructorName <br><br>
     * An accessor method that retrieves the instructor's name for the Course.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the instructor's name. <br>
     * @param None
     */
	public String getInstructorName()
	{
		return instructorName;
	} // end of getInstructorName()
	
	
	
	/** 
     * Name: getTeachingAssistantName <br><br>
     * An accessor method that retrieves the teaching assistant's name.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the teaching assistant's name. <br>
     * @param None
     */
	public String getTeachingAssistantName()
	{
		return teachingAssistantName;
	} // end of getteachingAssistantName()
	
	
	
	/** 
     * Name: getTeachingLocation <br><br>
     * An accessor method that retrieves the Location where the course is held.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the location of the Course. <br>
     * @param None
     */
	public Location getTeachingLocation()
	{
		return teachingLocation;
	} // end of getTeachingLocation()
	
	
	
	/** 
     * Name: getDaysHeld <br><br>
     * An accessor method that retrieves the days that the Course is held.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the days that the Course is held. <br>
     * @param None
     */
	public String getDaysHeld()
	{
		return daysHeld;
	} // end of getDaysHeld()
	
	
	
	/** 
     * Name: getTimeHeld <br><br>
     * An accessor method that retrieves when the Course is held.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the when the Course is held. <br>
     * @param None
     */
	public Time getTimeHeld()
	{
		return timeHeld;
	} // end of getTimeHeld()
	
	
	
	/** 
     * Name: getNumberOfWeeks <br><br>
     * An accessor method that retrieves the number of weeks for the Course.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the number of weeks for the Course. <br>
     * @param None
     */
	public int getNumberOfWeeks()
	{
		return numberOfWeeks;
	} // end of getNumberOfWeeks()
	
	
	
	/** 
     * Name: getNumberOfCredits <br><br>
     * An accessor method that retrieves the number of credits for the Course.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the number of credits for the Course. <br>
     * @param None
     */
	public int getNumberOfCredits()
	{
		return numberOfTotalCredits;
	} // end of getNumberOfCredits()
	
	
	
	/** 
     * Name: getCourseExcerpt <br><br>
     * An accessor method that retrieves the Course description.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the course description. <br>
     * @param None
     */
	public String getCourseExcerpt()
	{
		return courseExcerpt;
	} // end of getCourseExcerpt()
	
	
	
	/** 
     * Name: getStartDate <br><br>
     * An accessor method that retrieves the start date for the Course.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the starting date. <br>
     * @param None
     */
	public MonthDayYear getStartDate()
	{
		return startDate;
	} // end of getStartDate()
	
	
	
	/** 
     * Name: getEndingDate <br><br>
     * An accessor method that retrieves the end date for the Course.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the ending date. <br>
     * @param None
     */
	public MonthDayYear getEndDate()
	{
		return endDate;
	} // end of getEndDate()
	
	
	
	/** 
     * Name: getPrerequisitesNeededForThisCourse <br><br>
     * An accessor method that retrieves the prerequisites needed for this
     * Course.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the prerequisites needed for the Course. <br>
     * @param None
     */
	public ArrayList<String> getPrerequisitesNeededForThisCourse()
	{
		return prerequisitesNeededForThisCourse;
	} // end of getPrerequisitesNeededforthisCourse()
	
	
	
	/** 
     * Name: getWaitList <br><br>
     * An accessor method that retrieves the wait list.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the wait list. <br>
     * @param None
     */
	public ArrayList<User> getWaitList()
	{
		return waitList;
	} // end of getWaitList()
	
	
	
	/** 
     * Name: getWithdrawList <br><br>
     * An accessor method that retrieves the withdraw list.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns the withdraw list. <br>
     * @param None
     */
	public ArrayList<User> getWithdrawList()
	{
		return withdrawList;
	} // end of getDropAndWithdrawList()
	
	
	
	/** 
     * Name: setCourseID <br><br>
     * A mutator to change the courseID field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the courseID to the value passed in.
     * <br>
     * @param courseID - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setCourseID(String courseID) throws NullReferenceException
	{
		if(courseID == null)
			throw new NullReferenceException("Did not set the courseID " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.courseID = courseID;
	} // end of setCourse()
	
	
	
	/** 
     * Name: setStudentList <br><br>
     * A mutator to change the studentList field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the studentList to the value passed in.
     * <br>
     * @param studentList - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setStudentList(ArrayList<User> studentList) 
	                                              throws NullReferenceException
	{
		if(studentList == null)
			throw new NullReferenceException("Did not set the student list " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.studentList = studentList;
	} // end of setStudentList()
	
	
	
	/** 
     * Name: setSemester <br><br>
     * A mutator to change the semester field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the semester to the value passed in.
     * <br>
     * @param semester - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setSemester(String semester) throws NullReferenceException
	{
		if(semester == null)
			throw new NullReferenceException("Did not set the semester " +
					                         "because a null reference was " +
					                         "passed in!\n");
		this.semester = semester;
	} // end of setSemester()
	
	
	
	/** 
     * Name: setYear <br><br>
     * A mutator to change the year field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the year to the value passed in.
     * <br>
     * @param year - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a negative number is 
     *         passed in.
     */
	public void setYear(int year) throws NotValidArgumentException
	{
		if(year < 0)
			throw new NotValidArgumentException("Did not set the year " +
					                            "because a negative number " +
					                            "was passed in!\n");
		
		this.year = year;
	} // end of setYear()
	
	
	
	/** 
     * Name: setCapacity <br><br>
     * A mutator to change the capacity field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the capacity to the value passed in.
     * <br>
     * @param capacity - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a negative number is
     *         passed in.
     */
	public void setCapacity(int capacity) throws NotValidArgumentException
	{
		if(capacity < 0)
			throw new NotValidArgumentException("Did not set the capacity " +
					                            "because a negative number " +
					                            "was passed in!\n");
		
		this.capacity = capacity;
	} // end of setCapacity()
	
	
	
	/** 
     * Name: setCourseName <br><br>
     * A mutator to change the courseName field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the courseName to the value passed in.
     * <br>
     * @param courseName - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setCourseName(String courseName) throws NullReferenceException
	{
		if(courseName == null)
			throw new NullReferenceException("Did not set the course name " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.courseName = courseName;
	} // end of setCourseName()
	
	
	
	/** 
     * Name: setSectionNumber <br><br>
     * A mutator to change the sectionNumber field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the sectionNumber to the value passed in.
     * <br>
     * @param sectionNumber - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a null reference is 
     *         passed in.
     */
	public void setSectionNumber(int sectionNumber) 
	                                           throws NotValidArgumentException
	{
		if(sectionNumber < 0)
			throw new NotValidArgumentException("Did not set the section " +
					                            "number because a negative " +
					                            "number was passed in!\n");
		
		this.sectionNumber = sectionNumber;
	} // end of setSectionNumber()
	
	
	
	/** 
     * Name: setInstructorName <br><br>
     * A mutator to change the instructorName field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the instructorName to the value passed in.
     * <br>
     * @param instructorName - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setInstructorName(String instructorName)
	                                              throws NullReferenceException
	{
		if(instructorName == null)
			throw new NullReferenceException("Did not set the instructor's " +
					                         "name because a null reference " +
					                         "was passed in!\n");
		
		this.instructorName = instructorName;
	} // end of setInstructorName()
	
	
	
	/** 
     * Name: setTeachingAssistantName <br><br>
     * A mutator to change the teachingAssistantName field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the teachingAssistantName to the value passed in.
     * <br>
     * @param teachingAssistantName - the argument that will be used to set the
     *                                field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setTeachingAssistantName(String teachingAssistantName) 
	                                              throws NullReferenceException
	{
		if(teachingAssistantName == null)
			throw new NullReferenceException("Did not set the teaching " +
					                         "assistant's name because a " +
					                         "null reference was passed " +
					                         "in!\n");
		
		this.teachingAssistantName = teachingAssistantName;
	} // end of setTeachingAssitantName()
	
	
	
	/** 
     * Name: setTeachingLocation <br><br>
     * A mutator to change the teachingLocation field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the teachingLocation to the value passed in.
     * <br>
     * @param teachingLocation - the argument that will be used to set the
     *                           field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setTeachingLocation(Location teachingLocation) 
	                                              throws NullReferenceException
	{
		if(teachingLocation == null)
			throw new NullReferenceException("Did not set the teaching " +
					                         "location because a null " +
					                         "reference was passed in!\n");
		
		this.teachingLocation = teachingLocation;
	} // end of setTeachingLocation()
	
	
	
	/** 
     * Name: setDaysHeld <br><br>
     * A mutator to change the daysHeld field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the daysHeld to the value passed in.
     * <br>
     * @param daysHeld - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setDaysHeld(String daysHeld) 
	                                              throws NullReferenceException
	{
		if(daysHeld == null)
			throw new NullReferenceException("Did not set the days held " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.daysHeld = daysHeld;
	} // end of setDaysHeld()
	
	
	
	/** 
     * Name: setTimeHeld <br><br>
     * A mutator to change the timeHeld field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the timeHeld to the value passed in.
     * <br>
     * @param timeHeld - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setTimeHeld(Time timeHeld) throws NullReferenceException
	{
		if(timeHeld == null)
			throw new NullReferenceException("Did not set the time held " +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.timeHeld = timeHeld;
	} // end of setTimeHeld()
	
	
	
	/** 
     * Name: setNumberOfWeeks <br><br>
     * A mutator to change the numberOfWeeks field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the numberOfWeeks to the value passed in.
     * <br>
     * @param numberOfWeeks - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a null reference is
     *         passed in.
     */
	public void setNumberOfWeeks(int numberOfWeeks) 
	                                           throws NotValidArgumentException
	{
		if(numberOfWeeks < 0)
			throw new NotValidArgumentException("Did not set the number of " +
					                            "weeks because a negative " +
					                            "number was passed in!\n");
		
		this.numberOfWeeks = numberOfWeeks;
	} // end of setNumberOfWeeks()
	
	
	
	/** 
     * Name: setNumberOfCredits <br><br>
     * A mutator to change the numberOfCredits field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the numberOfCredits to the value passed in.
     * <br>
     * @param numberOfcrdits - the argument that will be used to set the field
     * @throws NotValidArgumentException is thrown when a null reference is 
     *         passed in.
     */
	public void setNumberOfCredits(int numberOfCredits) 
	                                           throws NotValidArgumentException
	{
		if(numberOfCredits < 0)
			throw new NotValidArgumentException("Did not set the number of " +
					                            "credits because a negative " +
					                            "number was passed in!\n");
		this.numberOfTotalCredits = numberOfCredits;
	} // end of setNumberOfCredits()
	
	
	
	/** 
     * Name: setCourseExcerpt <br><br>
     * A mutator to change the courseExcerpt field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the courseExcerpt to the value passed in.
     * <br>
     * @param courseExcerpt - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setCourseExcerpt(String courseExcerpt) 
	                                              throws NullReferenceException
	{
		if(courseExcerpt == null)
			throw new NullReferenceException("Did not set the course " +
					                         "excerpt because a null " +
					                         "reference was passed in!\n");
		
		this.courseExcerpt = courseExcerpt;
	} // end of setCourseExcerpt()
	
	
	
	/** 
     * Name: setStartDate <br><br>
     * A mutator to change the startDate field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the startDate to the value passed in.
     * <br>
     * @param startDate - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setStartDate(MonthDayYear startDate) 
	                                              throws NullReferenceException
	{
		if(startDate == null)
			throw new NullReferenceException("Did not set the start date " +
					                         "because a null reference was " +
					                         "passed in!\n");
		this.startDate = startDate;
	} // end of setStartDate()
	
	
	
	/** 
     * Name: setEndDate <br><br>
     * A mutator to change the endDate field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the endDate to the value passed in.
     * <br>
     * @param endDate - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setEndDate(MonthDayYear endDate) throws NullReferenceException
	{
		if(endDate == null)
			throw new NullReferenceException("Did not set the end date " +
					                         "because a null reference was " +
					                         "passed in!\n");
		this.endDate = endDate;
	} // end of setEndDate()
	
	
	
	/** 
     * Name: setPrerequisitesNeededForThisCourse <br><br>
     * A mutator to change the prerequisitesNeededforThisCourse field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the prerequisitesNeededForThisCourse to the value
     *                passed in.
     * <br>
     * @param prerequisitiesNeededForThisCourse - the argument that will be 
     *                                            used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setPrerequisitesNeededForThisCourse(
			               ArrayList<String> prerequisitiesNeededForThisCourse)
	                                             throws NullReferenceException
	{
		if(prerequisitiesNeededForThisCourse == null)
			throw new NullReferenceException("Did not set the prerequisites" +
					                         "because a null reference was " +
					                         "passed in!\n");
		
		this.prerequisitesNeededForThisCourse = 
			                                 prerequisitiesNeededForThisCourse;
	} // end of setPrerequisitesNeedForThisCourse()
	
	
	
	/** 
     * Name: setWaitList <br><br>
     * A mutator to change the waitList field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the waitList to the value passed in.
     * <br>
     * @param waitList - the argument that will be used to set the field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setWaitList(ArrayList<User> waitList) 
	                                              throws NullReferenceException
	{
		if(waitList == null)
			throw new NullReferenceException("Did not set the wait list " +
					                         "because a null reference was " +
					                         "passed in!\n");
		this.waitList = waitList;
	} // end of setWaitList()
	
	
	
	/** 
     * Name: setDropAndWithdrawList <br><br>
     * A mutator to change the dropAndWithdrawList field.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Changes the dropAndWithdrawList to the value passed in.
     * <br>
     * @param dropAndWithdrawList - the argument that will be used to set the
     *                              field
     * @throws NullReferenceException is thrown when a null reference is passed
     *         in.
     */
	public void setWithdrawList(ArrayList<User> withdrawList) 
	                                              throws NullReferenceException
	{
		if(withdrawList == null)
			throw new NullReferenceException("Did not set the drop and " +
					                         "withdraw list because a null" +
					                         "reference was passed in!\n");
		
		this.withdrawList = withdrawList;
	} // end of setDropAndWithdrawList()
	
	
	
	/** 
     * Name: compareTo <br><br>
     * Compares two objects and returns a number stating the ordering between
     * two objects.  A positive number states that the calling object would
     * come after the other object.  In contrast a negative number would
     * represent a smaller number.  Zero means that the two object are
     * equivalent.  The objects calling this needs to check for 
     * NullPointerExceptions at runtime, so have this inside a try block.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a number stating the ordering relationship 
     *                between the calling object and the argument. <br>
     * @param theOtherCourse - the other object will be compared
     * @throws NullPointerException is a unchecked exception that is thrown
     *         when a null argument is passed in
     */
	public int compareTo(Course theOtherCourse)
	{
		if(theOtherCourse == null)
			throw new NullPointerException("Can not compare the object " +
					                       "because a null reference was " +
					                       "passed in!\n");
		
		return courseID.compareTo(theOtherCourse.courseID);
	} // end of compareTo()
	
	
	
	/** 
     * Name: toString <br><br>
     * Displays the object's current state.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String object's state. <br>
     * @param None
     */
	public String toString()
	{
		return "Course Name: " + courseName + "\n" +
		       "Section:     " + sectionNumber + "\n" +
		       "Semester:    " + semester + "\n" +
		       "Year:        " + year + "\n" +
		       "Course ID:   " + courseID + "\n" +
		       "Instructor:  " + instructorName + "\n\n";
	} // end of toString()
	
	
	
	/** 
     * Name: showMoreInformation <br><br>
     * Displays more information than the toString() method about the Course.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String containing more course information. <br>
     * @param None
     */
	public String showMoreInformation()
	{
		return "Course Name: " + courseName + "\n" +
	           "Section:     " + sectionNumber + "\n" +
	           "Semester:    " + semester + "\n" +
	           "Year:        " + year + "\n" +
	           "Course ID:   " + courseID + "\n" +
	           "Credits:     " + numberOfTotalCredits + "\n" +
	           "Weeks:       " + numberOfWeeks + "\n" +
	           "Start Date:  " + startDate + "\n" +
	           "End Date:    " + endDate + "\n" +
	           "Time:        " + timeHeld.getStartingTime() + " - " +
	                             timeHeld.getEndingTime() + "\n" +
	           "Days:        " + printDaysHeld() + "\n" +
	           "Course Excerpt:" + "\n\n" + courseExcerpt + "\n" +
	           // prerequisites method here
	           "Instructor:  " + instructorName + "\n\n";
	} // end of showMoreInformation()
	
	
	
	/** 
     * Name: printDaysHeld <br><br>
     * Displays the Days the Course is held.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String holding the days the Course is held. <br>
     * @param None
     */
	private String printDaysHeld()
	{
		return daysHeld;
	} // end of printDaysHeld()
	
	
	
	/** 
     * Name: showStudentsInCourse <br><br>
     * Displays a String containing the student names.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a String showing the User in the course. <br>
     * @param None
     */
	public String showStudentsInCourse()
	{
		String listOfStudentNames = "";
		
		for(User theStudent: studentList)
		    listOfStudentNames += theStudent.getName() + "\n";
		
		return listOfStudentNames;
	} // end of showStudentsInCourse
	
	
	
	/** 
     * Name: isThereOpenSpotsLeftForTheClass <br><br>
     * Determines if there is spots open in the class.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if there is empty slots left
     *                for the course. <br>
     * @param None
     */
	public boolean isThereOpenSpotsLeftForTheClass()
	{
		return capacity > studentList.size();
	} // end of isThereOpenSoptsLeftTheClass()
	
	
	
	/** 
     * Name: isThereOpenSpotsLeftForTheWaitList <br><br>
     * Determines if there is spots open in the wait list.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if there is space left on the
     *                wait list. <br>
     * @param None
     */
	public boolean isThereOpenSpotsLeftForTheWaitList()
	{
		return NUMBER_OF_SPOTS_FOR_THE_WAITLIST > waitList.size();
	} // end of isThereOpenSpotsLetForTheWaitList()
	
	
	
	
	/** 
     * Name: equals <br><br>
     * Compares two objects and determines if they are equal.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the object are equal. <br>
     * @param otherTime - the Time that will be compared to the calling object
     */
	public boolean equals(Course compareToThis)
	{
		boolean areTheyEqual;
		
		if(compareToThis == null)
			areTheyEqual = false;
		
		else
			areTheyEqual = courseID.equals(compareToThis.courseID) &&
                           doTheUserListContainTheSameItems(
					                 studentList, compareToThis.studentList) &&
					                 
		                   semester.equals(compareToThis.semester) &&
		                   year == compareToThis.year &&
		                   capacity == compareToThis.capacity &&
		                   courseName.equals(compareToThis.courseName) &&
		                   sectionNumber == compareToThis.sectionNumber &&
		                   instructorName.equals(
		                		               compareToThis.instructorName) &&
		                		               
		                   teachingAssistantName.equals(
		                		        compareToThis.teachingAssistantName) &&
		                		        
		                   teachingLocation.equals(
		                		             compareToThis.teachingLocation) &&
		                		             
		                   daysHeld.equals(compareToThis.daysHeld) &&
		                   timeHeld.equals(compareToThis.timeHeld) &&
		                   numberOfWeeks == compareToThis.numberOfWeeks &&
		                   numberOfTotalCredits == 
		                	              compareToThis.numberOfTotalCredits &&
		                	              
		                   courseExcerpt.equals(compareToThis.courseExcerpt) &&
		                   startDate.equals(compareToThis.startDate) &&
		                   endDate.equals(compareToThis.endDate) &&
		                   
		                   doTheStringListContainTheSameItems(
			    		     prerequisitesNeededForThisCourse, 
			    		     compareToThis.prerequisitesNeededForThisCourse) &&
		                    
			    		   doTheUserListContainTheSameItems(
			    				           waitList, compareToThis.waitList) &&
		
		                   doTheUserListContainTheSameItems(withdrawList,
            		                               compareToThis.withdrawList);
		
		return areTheyEqual;
	} // end of equals()
	
	
	
    /** 
     * Name: doTheUserListContainTheSameItems <br><br>
     * Compares two ArrayList containing two User list and determines
     * if they contain the same elements.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the lists are equal. 
     * <br>
     * @param list1 - the first list that will be used in the comparison
     * @param list2 - the first list that will be used in the comparison
     */
    private boolean doTheUserListContainTheSameItems(ArrayList<User> list1,
    		                                         ArrayList<User> list2)
    {
    	boolean theListAreTheSame = true;
    	
    	// checking the sizes are equivalent first
    	if(list1.size() != list2.size())
    		theListAreTheSame = false;
    	
    	for(int i = 0; i < list1.size() && theListAreTheSame == true; i++)
    		if(list1.get(i).equals(list2.get(i)))
    			theListAreTheSame = false;
    	
    	return theListAreTheSame;
    } // end of doTheUserListContainTheSameItems()

    
    
    /** 
     * Name: doTheStringListContainTheSameItems <br><br>
     * Compares two ArrayList containing two String list and determines
     * if they contain the same elements.
     * <br><br>
     * Precondition: None <br>
     * Postcondition: Returns a boolean stating if the lists are equal. 
     * <br>
     * @param list1 - the first list that will be used in the comparison
     * @param list2 - the first list that will be used in the comparison
     */
    private boolean doTheStringListContainTheSameItems(ArrayList<String> list1,
    		                                           ArrayList<String> list2)
    {
    	boolean theListAreTheSame = true;
    	
    	// checking the sizes are equivalent first
    	if(list1.size() != list2.size())
    		theListAreTheSame = false;
    	
    	for(int i = 0; i < list1.size() && theListAreTheSame == true; i++)
    		if(list1.get(i).equals(list2.get(i)))
    			theListAreTheSame = false;
    	
    	return theListAreTheSame;
    } // end of doTheStringListContainTheSameItems()
} // end of Course class